﻿@using Gurux.DLMS.AMI.Client.Pages.Agent;
@using Gurux.DLMS.AMI.Client.Pages.Block;
@using Gurux.DLMS.AMI.Client.Pages.ComponentView;
@using Gurux.DLMS.AMI.Client.Pages.Device;
@using Gurux.DLMS.AMI.Client.Pages.DeviceTemplate;
@using Gurux.DLMS.AMI.Client.Pages.Gateway;
@using Gurux.DLMS.AMI.Client.Pages.KeyManagement;
@using Gurux.DLMS.AMI.Client.Pages.Module;
@using Gurux.DLMS.AMI.Client.Pages.Schedule;
@using Gurux.DLMS.AMI.Client.Pages.Script;
@using Gurux.DLMS.AMI.Client.Pages.Subtotal
@using Gurux.DLMS.AMI.Client.Pages.Trigger;
@using Gurux.DLMS.AMI.Client.Pages.Workflow;
@using Gurux.DLMS.AMI.Shared.DIs
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs
@using Gurux.DLMS.AMI.Shared.DTOs.Authentication
@using Gurux.DLMS.AMI.Shared.Rest
@using Microsoft.AspNetCore.SignalR.Client
@using Gurux.DLMS.AMI.Shared
@using Gurux.DLMS.AMI.Shared.Enums
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module
@using System.Linq

@inject HttpClient Http
@inject IGXNotifier Notifier

<SelectionContainer TItem="GXUserGroup" @ref="@_selectionContainer">
    <SelectionList Title="Selected" @ref="_selected"
                   ShowAllUsers="false"
                   ItemsProvider="@GetSelectedItems">
        <DataContent>
            @context.Name
        </DataContent>
        <FilterContent>
            <Search Placeholder="@Properties.Resources.FilterByName"
                    OnClickAsync="@SearchSelectedByName" />
        </FilterContent>
    </SelectionList>
    <SelectionList Title="Available" @ref="_available"
                   ItemsProvider="@GetItems">
        <DataContent>
            @context.Name
        </DataContent>
        <FilterContent>
            <Search Placeholder="@Properties.Resources.FilterByName"
                    OnClickAsync="@SearchByName" />
            <Search Placeholder="@Properties.Resources.FilterByUser"
                    OnClickAsync="@SearchByUser" />
        </FilterContent>
    </SelectionList>
</SelectionContainer>

@code {

    [CascadingParameter]
    private UserTab? UserParent { get; set; }
    [CascadingParameter]
    private DeviceGroupTab? DeviceGroupParent { get; set; }
    [CascadingParameter]
    private AgentGroupTab? AgentGroupParent { get; set; }
    [CascadingParameter]
    private ModuleGroupTab? ModuleGroupParent { get; set; }
    [CascadingParameter]
    private WorkflowGroupTab? WorkflowGroupParent { get; set; }

    [CascadingParameter]
    private TriggerGroupTab? TriggerGroupParent { get; set; }
    [CascadingParameter]
    private BlockGroupTab? BlockGroupParent { get; set; }

    [CascadingParameter]
    private ComponentViewGroupTab? ComponentViewGroupParent { get; set; }
    [CascadingParameter]
    private ScriptGroupTab? ScriptGroupParent { get; set; }
    [CascadingParameter]
    private DeviceTemplateGroupTab? DeviceTemplateParent { get; set; }

    [CascadingParameter]
    private KeyManagementGroupTab? KeyManagementParent { get; set; }

    [CascadingParameter]
    private ScheduleGroupTab? ScheduleGroupParent { get; set; }

    [CascadingParameter]
    private GatewayGroupTab? GatewayGroupParent { get; set; }

    [CascadingParameter]
    private SubtotalGroupTab? SubtotalGroupParent { get; set; }

    SelectionList<GXUserGroup>? _selected;
    SelectionList<GXUserGroup>? _available;
    SelectionContainer<GXUserGroup>? _selectionContainer;

    /// <summary>
    /// User group filter.
    /// </summary>
    private GXUserGroup filter = new GXUserGroup(null);

    protected async Task SearchSelectedByName(string? name)
    {
        try
        {
            if (_selected?.Items != null)
            {
                _selected.HiddenItems.Clear();
                if (!string.IsNullOrEmpty(name))
                {
                    name = name.ToLower();
                    foreach (var it in _selected.Items)
                    {
                        if (it.Name != null && !it.Name.ToLower().Contains(name))
                        {
                            _selected.HiddenItems.Add(it);
                        }
                    }
                }
                Notifier?.ClearStatus();
                await _selected.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    protected async Task SearchByName(string? name)
    {
        try
        {
            if (_available != null)
            {
                filter.Name = name;
                Notifier?.ClearStatus();
                await _available.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    protected async Task SearchByUser(string? userName)
    {
        try
        {
            if (_available != null)
            {
                if (string.IsNullOrEmpty(userName))
                {
                    filter.Users = null;
                }
                else
                {
                    GXUser? user = filter.Users?.FirstOrDefault();
                    if (user == null)
                    {
                        user = new();
                        filter.Users = new(new GXUser[] { user });
                    }
                    user.UserName = userName;
                }
                Notifier?.ClearStatus();
                await _available.RefreshDataAsync();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    /// <summary>
    /// Filter is done when SearchSelectedByName is called.
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private ValueTask<ItemsProviderResult<GXUserGroup>> GetSelectedItems(GXItemsProviderRequest request)
    {
        if (_selected?.Items == null)
        {
            return default;
        }
        //ToArray makes a clone from the items. Don't remove it.
        return new(new ItemsProviderResult<GXUserGroup>(_selected.Items.ToArray(), _selected.Items.Count));
    }

    private async ValueTask<ItemsProviderResult<GXUserGroup>> GetItems(GXItemsProviderRequest request)
    {
        //Don't clear status or error is lost.
        Notifier?.ProgressStart();
        try
        {
            ListUserGroups req = new ListUserGroups()
                {
                    Index = request.StartIndex,
                    Count = request.Count,
                    Filter = filter,
                    Descending = request.Descending,
                    AllUsers = request.ShowAllUserData,
                    Exclude = _selected?.Items?.Select(s => s.Id).ToArray()
                };
            var ret = await Http.PostAsJson<ListUserGroupsResponse>("api/UserGroup/List", req, request.CancellationToken);
            if (ret?.UserGroups != null && _selected != null)
            {
                return new ItemsProviderResult<GXUserGroup>(ret.UserGroups, ret.Count);
            }
        }
        catch (TaskCanceledException)
        {
            //Let the table component handle this.
            throw;
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
        return default;
    }

    protected override async Task OnInitializedAsync()
    {
        //Wait until table is loaded. Don't remove this or selector is null.
        await Task.Delay(1);
        try
        {
            Notifier.ProgressStart();
            Notifier.ClearStatus();
            if (_selectionContainer == null || _selected == null)
            {
                throw new ArgumentException(Properties.Resources.InvalidTarget);
            }
            CrudAction action;
            //Get selected user groups.
            if (ScheduleGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = ScheduleGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(ScheduleGroupParent.Action);
            }
            else if (DeviceTemplateParent?.Active?.UserGroups != null)
            {
                _selected.Items = DeviceTemplateParent.Active.UserGroups;
                action = ClientHelpers.GetAction(DeviceTemplateParent.Action);
            }
            else if (DeviceGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = DeviceGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(DeviceGroupParent.Action);
            }
            else if (AgentGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = AgentGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(AgentGroupParent.Action);
            }
            else if (ModuleGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = ModuleGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(ModuleGroupParent.Action);
            }
            else if (WorkflowGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = WorkflowGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(WorkflowGroupParent.Action);
            }
            else if (TriggerGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = TriggerGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(TriggerGroupParent.Action);
            }
            else if (BlockGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = BlockGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(BlockGroupParent.Action);
            }
            else if (ComponentViewGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = ComponentViewGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(ComponentViewGroupParent.Action);
            }
            else if (ScriptGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = ScriptGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(ScriptGroupParent.Action);
            }
            else if (UserParent?.Active?.UserGroups != null)
            {
                _selected.Items = UserParent.Active.UserGroups;
                action = ClientHelpers.GetAction(UserParent.Action);
            }
            else if (KeyManagementParent?.Active?.UserGroups != null)
            {
                _selected.Items = KeyManagementParent.Active.UserGroups;
                action = ClientHelpers.GetAction(KeyManagementParent.Action);
            }
            else if (GatewayGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = GatewayGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(GatewayGroupParent.Action);
            }
            else if (SubtotalGroupParent?.Active?.UserGroups != null)
            {
                _selected.Items = SubtotalGroupParent.Active.UserGroups;
                action = ClientHelpers.GetAction(SubtotalGroupParent.Action);
            }
            else
            {
                throw new Exception(Properties.Resources.InvalidTarget);
            }
            bool addDefaultGroups = action == CrudAction.Create && !_selected.Items.Any();
            if (addDefaultGroups)
            {
                //Show default groups when new group is added.
                ListUserGroups req = new ListUserGroups()
                    {
                        Filter = new GXUserGroup()
                        {
                            Default = true
                        },
                        Count = _selectionContainer.PageSize,
                        Exclude = _selected.Items.Select(s => s.Id).ToArray()
                    };
                var ret = await Http.PostAsJson<ListUserGroupsResponse>("api/UserGroup/List", req);
                if (ret?.UserGroups != null)
                {
                    _selected.Items.AddRange(ret.UserGroups);
                }
            }
            //Read available items.
            if (_available != null)
            {
                await _available.RefreshDataAsync();
            }
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
    }
}

